/**
 * 北谷信息科技（广州）有限公司拥有本软件所有版权 © 2022，并保留所有权利。
 * Copyright © 2022, North Valley Information Technology (Guangzhou) Company
 * Limited, All Rights Reserved.
 */

package main.com.scrapy.utils;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.io.Reader;
import java.net.URL;
import java.net.URLConnection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Random;
import java.util.stream.Collectors;
import java.util.zip.GZIPInputStream;
import javax.script.Invocable;
import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
import org.jsoup.Connection;
import org.jsoup.Connection.Method;
import org.jsoup.Connection.Response;
import org.jsoup.Jsoup;
import org.jsoup.internal.StringUtil;
import org.jsoup.nodes.Document;

/**
 * 请求工具类
 *
 * @author Double
 * <p><b>Creation Time:</b> 2022/9/17 22:01</p>
 * @since scrapy-1688
 */
public class HttpUtil {

  public static final String HTTP_PREFIX = "https://";
  public static final String COMPANY_URL = "https://s.1688.com/company/company_search.htm";
  public static final String COMPANY_FILE_URL = "https://sale.1688.com/factory/card.html";
  //  public static final String COMPANY_URL = "https://sale.1688.com/factory/home.html";
  public static final String PRODUCT_URL = "https://s.1688.com/selloffer/offer_search.html";

  public static final String USER_AGENT = "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/102.0.0.0 Safari/537.36";
  public static final String CONTENT_TYPE = "text/html";

  /**
   * 请求参数拼接
   *
   * @param map
   * @return
   */
  public static String createParams(Map<String, Object> map) {
    List<String> params = map.entrySet().stream().map(t -> t.getKey() + "=" + t.getValue())
        .collect(Collectors.toList());
    return StringUtil.join(params, "&");
  }

  public static Document getHttpDocument(String url) throws IOException {
    Response response = Jsoup.connect(url).method(Method.GET).execute();
    return response.parse();
  }

  public static Document getHttpDocument2(String url, Map<String, Object> map,
      Map<String, String> params) throws IOException {
    url = map == null ? url : url + "?" + createParams(map);
    Response response = Jsoup.connect(url).method(Method.GET).ignoreContentType(true).data(params)
        .execute();
    return response.parse();
  }

  public static Document getHttpDocument(String url, Map<String, Object> map,
      Map<String, String> params, String cookie) throws IOException {
    url = map == null ? url : url + "?" + createParams(map);
    //ignoreContentType(true) : Unhandled content type. Must be text/*, application/xml, or application/*+xml. Mimetype=application/json;charset=UTF-8
    Connection connection = Jsoup.connect(url).userAgent(USER_AGENT).ignoreContentType(true)
        .header("content-type", CONTENT_TYPE);
    if (params != null) {
      connection.data(params);
    }
    if (cookie != null) {
      connection.header("cookie", cookie);
    }
    return connection.get();
  }

  public static Document getHttpDocument2(String url, Map<String, Object> map,
      Map<String, String> params, Map<String, String> cookies) throws IOException {
    url = map == null ? url : url + "?" + createParams(map);
    //ignoreContentType(true) : Unhandled content type. Must be text/*, application/xml, or application/*+xml. Mimetype=application/json;charset=UTF-8
    Connection connection = Jsoup.connect(url).userAgent(USER_AGENT).ignoreContentType(true)
        .header("content-type", CONTENT_TYPE);
    if (params != null) {
      connection.data(params);
    }
    if (cookies != null) {
      //      connection.header("cookie", cookie);
      connection.cookies(cookies);
    }
    return connection.get();
  }

  public static String getHttpResponse(String url) throws IOException {
    CloseableHttpClient httpClient = HttpClients.createDefault();
    HttpGet httpGet = new HttpGet(url);
    httpGet.setHeader("User-Agent", USER_AGENT);
    CloseableHttpResponse response = httpClient.execute(httpGet);
    return EntityUtils.toString(response.getEntity(), "utf-8");
  }

  public static String getHttpResponse2(String url) throws IOException {
    PrintWriter out = null;
    BufferedReader in = null;
    StringBuilder result = new StringBuilder();
    String urlNameString = url;
    URL realUrl = new URL(urlNameString);
    URLConnection conn = realUrl.openConnection();
    conn.setRequestProperty("accept", "*/*");
    conn.setRequestProperty("connection", "Keep-Alive");
    conn.setRequestProperty("user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)");
    conn.setRequestProperty("Accept-Charset", "utf-8");
    conn.setRequestProperty("Content-Type", "application/json;charset=utf-8");
    conn.setDoOutput(true);
    conn.setDoInput(true);
    out = new PrintWriter(conn.getOutputStream());
    out.flush();
    GZIPInputStream gzip = new GZIPInputStream(conn.getInputStream());
    in = new BufferedReader(new InputStreamReader(gzip, "utf-8"));

    String line;
    while ((line = in.readLine()) != null) {
      result.append(line);
    }
    System.out.println("response" + new String(result.toString().getBytes(), "UTF-8"));
    return new String(result.toString().getBytes(), "UTF-8");
  }

  public static String createSign(String cookies, long timestamp, String data) throws Exception {
    ScriptEngineManager maneger = new ScriptEngineManager();
    ScriptEngine engine = maneger.getEngineByName("JavaScript");
    String projectDir = System.getProperty("user.dir");
    File file = new File(projectDir + "/script/createSign.js");
    FileInputStream fileInputStream = new FileInputStream(file);
    Reader scriptReader = new InputStreamReader(fileInputStream, "utf-8");
    engine.eval(scriptReader);

    // 调用JS方法
    String tokenKey = JsonUtil.getJsonResult(cookies, "_m_h5_tk=(.*?)_").get(0);
    String token = tokenKey.substring(9, tokenKey.length() - 1);
    String appKey = "12574478";
    String param = token.concat("&").concat(String.valueOf(timestamp)).concat("&").concat(appKey)
        .concat("&").concat(data);

    Invocable invocable = (Invocable) engine;
    Object createSign = invocable.invokeFunction("createSign", new Object[]{param});
    return (String) createSign;
  }

  public static Connection.Response simulateLogin() throws IOException {
    /*模拟登陆*/
    String loginUrl = "https://s.1688.com";
    Map<String, String> headers = new HashMap<>();
    //模拟浏览器的头部
    headers.put("authority", "s.1688.com");
    headers.put("method", "GET");
    headers.put("path", "/");
    headers.put("scheme", "https");
    headers.put("accept",
        "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9");
    headers.put("accept-encoding", "gzip, deflate, br");
    headers.put("accept-language", "zh-CN,zh;q=0.9");
    headers.put("cache-control", "max-age=31536000");
    headers.put("pragma", "no-cache");
    headers.put("upgrade-insecure-requests", "1");
    headers.put("cookie",
        "cna=JmazGywzwX4CAcppQ5ycmKXc; xlly_s=1; keywordsHistory=雨伞大量批发; ali_ab=202.105.67.156.1663858747637.0; lid=火影340361; ali_apache_track=c_mid=b2b-2699915560d7b56|c_lid=火影340361|c_ms=1; last_mid=b2b-2699915560d7b56; is_identity=buyer; alicnweb=touch_tb_at=1663862645391|lastlogonid=%E7%81%AB%E5%BD%B1340361; aliwwLastRefresh=1663862988408; aliwwLastNum=0; _m_h5_tk=7ae5a2a1707d8be39293b73dda154eb4_1663927432758; _m_h5_tk_enc=b9eb7eafa3504625bb2c3f92a5e0d12d; cookie2=14dc8f023128ac93ee7119a3baaef4e1; t=eccd5e5e077ffa1a09526f1e54200a4e; _tb_token_=e05956e36ed00; cookie1=B0TxOpjr2JCF+44+OeKepZKUpHkbqvsbHpjUfIhTUvo=; cookie17=UU6oIK+/RH65Cg==; sgcookie=E100Pu5QpjWAuChATOojSM9/lCSeZaE0JOKHTjkmVyY+l+uIc1gcVgexvsxTghBUaPlZP5v+LHGtvaE20urGa/09uPBJDoxxKb72JfX/yhE/IQI=; sg=105; csg=6dd13948; unb=2699915560; uc4=id4=0@U2xlrqyvlIk344O0AhYhJjuT42Bo&nk4=0@2h3pD0fUr2ST4Nrg2Mo0Ih4JB6S5; __cn_logon__=true; __cn_logon_id__=火影340361; ali_apache_tracktmp=c_w_signed=Y; _nk_=\\u706B\\u5F71340361; _csrf_token=1663917552778; _is_show_loginId_change_block_=b2b-2699915560d7b56_false; _show_force_unbind_div_=b2b-2699915560d7b56_false; _show_sys_unbind_div_=b2b-2699915560d7b56_false; _show_user_unbind_div_=b2b-2699915560d7b56_false; __rn_alert__=false; tfstk=cgTGBbD76hS1ihuvdd_sud2wAudcZFDNQE898fdVcXq5_T8FicZU4NnKt9kSQo1..; l=eBxB60_VTrIaie0SKOfZourza7797IRAguPzaNbMiOCP9Hfv5q4PW6oQogYJCnGVhsUwR3z0twiMBeYBqCcmdj4K47Gok4Mmn; isg=BCoqjzk-PciOpbGlnHu0hoQKe5DMm671riO4kbTjwn0I58qhnCuaBf0ddxN7FyaN");
    //随机数
    Random random = new Random();
    //获得配置文件的用户
    //    Integer index = random.nextInt(loginUsers.getUserList().size());
    //获取随机的用户信息
    //    String user = loginUsers.getUserList().get(index);
    //    String[] userArray = user.split(",");
    //账号
    //    String userName = "zhangdsby";
    //密码
    //    String userPassword = "7c09643e07eafa8434783157c751ae208984a38d27e48fc69f96a458e9a891e7ec04b3d63206059ef20fb09d4369ba7641f19e18a2bdb5ad227548eb20f4f290e28af28ac3a33e317887d90f590e11d42a8d22bba7acfa19d40c611f04e30a89cc3bb73dce7313528966b9a01151612bfa98af29015fb18e4e39cfcf9fc38403";
    Connection loginConnection = Jsoup.connect(loginUrl);
    //    loginConnection.followRedirects(false);
    //    loginConnection.headers(headers);
    //写入用户名与密码,TPL_username为form表单的用户名输入input,TPL_password为form表单的密码输入input
    //    loginConnection.data("loginId", userName).data("password2", userPassword).timeout(50000)
    //        .ignoreContentType(true).userAgent(
    //            "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.87 Safari/537.36")
    //        .method(Connection.Method.POST);
    Connection.Response rep = loginConnection.execute();
    System.out.println("登陆信息:" + rep.body());
    //生成5到15秒的时间用来休眠
    Integer sleepTime = random.nextInt(10000) + 5000;
    try {
      Thread.sleep(sleepTime);
    } catch (InterruptedException e) {
    }
    return rep;
  }

}
